import threading, subprocess, time, csv, io

from .process import BccProcess, PerfProcess


class CmdThread(threading.Thread):
    """CmdThread inherits thread

    To not block main thread, so wrap the commands in a new thread.

    Attributes:
        cmd: cmd to be executed
        process_type: process type to handle output of cmd
        output: output file path
    """

    def __init__(self, cmd, process_type, output):
        super().__init__()
        self.cmd = cmd
        self.process_type = process_type
        self.output = output

    def cmdline(self):
        # startTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        # print("now", startTime, "cmd", self.cmd)
        proc = subprocess.Popen(self.cmd, stdout=subprocess.PIPE, shell=True)
        out, err = proc.communicate()  # this blocks the thread until cmd finishs

        if err:
            print("%s failed with error %s" % (self.cmd, err))  # TODO use logging
            return

        if self.process_type == "log2":
            hist = BccProcess.process_log2(out)
            self.write(hist)
        # TODO: other bcc traces process

        if self.process_type == "perfstat":
            perfres = PerfProcess.process_perf_stat(out)
            self.write(perfres)

    def write(self, data):
        """add timestamp, and write row to output file"""
        endTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        row = [endTime]
        row.extend(data)

        # save perf stat result
        with open(self.output, "a+") as csvfile:
            csvWriter = csv.writer(csvfile, delimiter=",")
            csvWriter.writerow(row)

    def run(self):
        self.cmdline()


class StreamThread(threading.Thread):
    """CachestatThread inherits thread

    This thread execute bcc cachestat, and save stream output

    Attributes:
        cmd: cmd to be executed
        process_type: process type to handle output of cmd
        output: output file path
    """

    def __init__(self, cmd, output):
        super().__init__()
        self.cmd = cmd
        self.output = output
        self.firstRow = True

    def cmdline(self):
        # startTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        # print("now", startTime, "cmd", self.cmd)
        with subprocess.Popen(self.cmd, stdout=subprocess.PIPE, shell=True) as proc:
            while proc.poll() is None:
                line = proc.stdout.readline().decode("utf-8").rstrip()
                data = line.split()
                self.write(data)

    def write(self, data):
        """add timestamp, and write row to output file"""
        endTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        row = [endTime] if not self.firstRow else ["TIME"]
        row.extend(data)
        self.firstRow = False

        # save perf stat result
        with open(self.output, "a+") as csvfile:
            csvWriter = csv.writer(csvfile, delimiter=",")
            csvWriter.writerow(row)

    def run(self):
        self.cmdline()
